package com.wontube.client.extension.utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author yuechao
 * 
 */
public final class FileUtils {
	private final static Logger logger = LoggerFactory.getLogger(FileUtils.class);
	
	private FileUtils() {
	}

	public static String[] readAllLines(File file) throws IOException {
		if (!file.exists()) {
			return new String[0];
		}

		FileInputStream stream = new FileInputStream(file);
		BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));

		try {
			ArrayList<String> list = new ArrayList<String>();
			while (true) {
				String line = reader.readLine();
				if (line == null ) {
					break;
				}
				list.add(line);
			}
			return list.toArray(new String[0]);
		} finally {
			stream.close();
			reader.close();
		}
	}
	
	public static String readAllText(File file) throws IOException {
		if (!file.exists()) {
			return "";
		}

		FileInputStream stream = new FileInputStream(file);
		InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
		try {
			return readAllText(reader);
		} finally {
			stream.close();
			reader.close();
		}
	}

	public static String readAllText(Reader reader) throws IOException {
		StringBuilder sb = new StringBuilder();
		char[] cbuffer = new char[512];
		while (true) {
			int len = reader.read(cbuffer, 0, cbuffer.length);
			if (len <= 0) {
				break;
			}
			sb.append(cbuffer, 0, len);
		}

		return sb.toString();
	}

	/**
	 * @param path
	 * @param root
	 * @return
	 */
	public static String getRelativePath(String fullPath, String rootPath) {
		int index = rootPath.length();
		if (!rootPath.endsWith("/") && !rootPath.endsWith("\\")) {
			index++;
		}

		String relativePath = fullPath.substring(index);

		return relativePath;
	}

	/**
	 * @param dir
	 * @param suffix
	 * @return
	 */
	public static ArrayList<String> findFiles(String dir, String... suffixList) {
		File root = new File(dir);
		ArrayList<String> lst = new ArrayList<String>();
		_findFiles(lst, root, suffixList);

		return lst;
	}

	/**
	 * @param dir
	 * @param suffix
	 * @return
	 */
	private static void _findFiles(ArrayList<String> lst, File dir, String... suffixList) {
		for (File file : dir.listFiles()) {
			if (file.isFile()) {
				boolean flag = false;
				for (String suffix : suffixList) {
					if (file.getName().endsWith(suffix)) {
						flag = true;
						break;
					}
				}

				if (flag) {
					lst.add(file.getAbsolutePath());
				}

			} else if (file.isDirectory()) {
				_findFiles(lst, file, suffixList);
			}
		}
	}

	public static boolean deleteFile(File file) {
		if (file.isFile()) {
			if (!file.delete()) {
				return false;
			}
		} else {
			for (File childFile : file.listFiles()) {
				if (!FileUtils.deleteFile(childFile)) {
					return false;
				}
			}
			file.delete();
		}

		return true;
	}

	/**
	 * @param path1
	 * @param path2
	 * @return
	 */
	public static String combinePath(String path1, String path2) {
		if (StringUtils.isNullOrEmpty(path1) && StringUtils.isNullOrEmpty(path2)) {
			return "";
		}

		if (StringUtils.isNullOrEmpty(path1)) {
			return path2;
		}

		if (StringUtils.isNullOrEmpty(path2)) {
			return path1;
		}

		StringBuffer buf = new StringBuffer(path1.length() + path2.length() + 2);
		buf.append(path1);
		switch (buf.charAt(buf.length() - 1)) {
		case '\\':
		case '/':
			switch (path2.charAt(0)) {
			case '\\':
			case '/':
				buf.append(path2.substring(1));
				break;

			default:
				buf.append(path2);
				break;
			}
			break;

		default:
			switch (path2.charAt(0)) {
			case '\\':
			case '/':
				buf.append(path2);
				break;

			default:
				buf.append(File.separatorChar);
				buf.append(path2);
				break;
			}
			break;
		}

		return buf.toString();
	}

	/**
	 * @param args
	 * @return
	 */
	public static String combinePath(String... args) {
		if (args.length < 1) {
			return "";
		}

		int index = 0;
		StringBuffer buffer = new StringBuffer();
		while (index < args.length && args[index].length() <= 0) {
			index++;
		}
		if (args.length > index) {
			buffer.append(args[index]);
			for (int i = index + 1; i < args.length; i++) {
				combinePath(buffer, args[i]);
			}
		}
		return buffer.toString();
	}

	private static StringBuffer combinePath(StringBuffer pathBuf, String pathOther) {
		if (StringUtils.isNullOrEmpty(pathOther)) {
			return pathBuf;
		}

		switch (pathBuf.charAt(pathBuf.length() - 1)) {
		case '\\':
		case '/':
			switch (pathOther.charAt(0)) {
			case '\\':
			case '/':
				pathBuf.append(pathOther.substring(1));
				break;

			default:
				pathBuf.append(pathOther);
				break;
			}
			break;

		default:
			switch (pathOther.charAt(0)) {
			case '\\':
			case '/':
				pathBuf.append(pathOther);
				break;

			default:
				pathBuf.append(File.separatorChar);
				pathBuf.append(pathOther);
				break;
			}
			break;
		}

		return pathBuf;
	}
	
	/**
	 * 读取网络数据并保存在文件中
	 * @param url
	 * @param file
	 * @return
	 * @throws IOException 
	 */
	public static boolean fetchAndSave(String url, File file) throws IOException{
		File p = file.getParentFile();
		if(p != null && ! p.exists()){
			p.mkdirs();
		}
		
		HttpURLConnection conn = null;
		ByteArrayOutputStream byteOutput = null;
		BufferedInputStream bsf = null;
		FileOutputStream fos = null;
		byte[] bufs = new byte[1024];
		
		try {
			conn = (HttpURLConnection)new URL(url).openConnection();
			byteOutput = new ByteArrayOutputStream();
			bsf = new BufferedInputStream(conn.getInputStream());
			
			while(true){
				int len = bsf.read(bufs);
				if(len <= 0){
					break;
				}
				
				byteOutput.write(bufs, 0, len);
			}
			
			byteOutput.flush();
			if(byteOutput.size() > 0){
				fos = new FileOutputStream(file);
				fos.write(byteOutput.toByteArray());
				fos.flush();
				return true;
			}else{
				logger.warn("fetch empty content from {}.", url);
				return false;
			}		
		} finally {
			conn.disconnect();
			if(fos != null){
				fos.close();
			}
			if(bsf != null){
				bsf.close();
			}
			
			if(byteOutput != null){
				byteOutput.close();
			}
		}			
	}
	
	public static boolean saveToFile(String content, File file){
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			fos.write(content.getBytes());
		} catch (Exception e) {
			return false;
		} finally {
			if(fos != null){
				try {
					fos.close();
				} catch (Exception e) {					
				}			
			}
		}
		
		return true;
	}
}
